#include "StdAfx.h"
#include "TextUnit.h"
#include "MyRectTracker.h"
#include "DataFlow.h"
#include "ArrowUnit.h"

CTextUnit::CTextUnit(void): m_caretPos(0), m_caretPt(0)
{
	m_Tracker=new CMyRectTracker();
	((CMyRectTracker*)m_Tracker)->m_nStyle=CRectTracker::resizeOutside | CRectTracker::dottedLine;
	m_text.clear();
	OneRowText temp;
	temp.text = _T("");
	temp.textPt = (0, 0);
	m_text.push_back(temp);
	m_caretPos.x = 1;
	m_caretPos.y = 0;
	m_BorderOn=FALSE;
}

CTextUnit::~CTextUnit(void)
{
}
void CTextUnit::ShowBorder(BOOL border)
{
	m_BorderOn=border;
}
void CTextUnit::Preview(CDC* pDC)
{
	CPen pen;
	pen.CreatePen(PS_DOT,1,RGB(0,0,0));
	CPen* oldpen=pDC->SelectObject(&pen);
	pDC->Rectangle(m_BeginPoint.x,m_BeginPoint.y,m_EndPoint.x,m_EndPoint.y);
	pDC->SelectObject(oldpen);
}
void CTextUnit::Draw(CDC* pDC)
{
	if (m_BorderOn)
	{
		pDC->Rectangle(m_BeginPoint.x,m_BeginPoint.y,m_EndPoint.x,m_EndPoint.y);
	}	
	ShowText(pDC, true);
	CalTextPos(pDC);
	//ShowText(pDC, false);
}
BOOL CTextUnit::OnHitTest(CPoint* point)
{
	CRgn rgn;
	rgn.CreateRectRgn(m_BeginPoint.x,m_BeginPoint.y,m_EndPoint.x,m_EndPoint.y);
	if (rgn.PtInRegion(*point))
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
void CTextUnit::Save(CArchive& out)
{
	out<<CString("Text");
	out<<(int)m_text.size();
	for (vector<OneRowText>::iterator it=m_text.begin(); it!=m_text.end(); it++)
	{
		out<<it->textPt;
		out<<it->text;
	}
	CUnit::Save(out);
}
void CTextUnit::Load(CArchive& in)
{
	int size;
	in>>size;
	for (int i=0; i<size; i++)
	{
		CPoint point;
		in>>point;
		CString str;
		in>>str;
		OneRowText ort(point,str);
		m_text.insert(m_text.end(),ort);
	}
	m_BorderOn=false;
	CUnit::Load(in);

}
void CTextUnit::Track(CWnd* parent,CPoint* point)
{
	m_Tracker->Track(parent,*point);
	CPoint old_begin=m_BeginPoint;
	CPoint old_end=m_EndPoint;
	int tmpx=m_BeginPoint.x;
	int tmpy=m_BeginPoint.y;
	int width=m_EndPoint.x-m_BeginPoint.x;
	int height=m_EndPoint.y-m_BeginPoint.y;
	int begin_dx=m_BeginPoint.x-((CMyRectTracker*)m_Tracker)->m_rect.TopLeft().x;
	int begin_dy=m_BeginPoint.y-((CMyRectTracker*)m_Tracker)->m_rect.TopLeft().y;
	int end_dx=m_EndPoint.x-((CMyRectTracker*)m_Tracker)->m_rect.BottomRight().x;
	int end_dy=m_EndPoint.y-((CMyRectTracker*)m_Tracker)->m_rect.BottomRight().y;
	if (begin_dx!=0 || begin_dy!=0 || end_dx!=0 || end_dy!=0)
	{
		CUnit* father=theApp.m_UnitManager->GetFather(this);
		father->DeleteChild(this);
	}
	m_BeginPoint=((CMyRectTracker*)m_Tracker)->m_rect.TopLeft();
	m_EndPoint=((CMyRectTracker*)m_Tracker)->m_rect.BottomRight();
	if (begin_dx!=0 || begin_dy!=0 || end_dx!=0 || end_dy!=0)
	{
		theApp.m_UnitManager->AddShape(this);
	}

	int begin_off_x=m_BeginPoint.x-old_begin.x;
	int begin_off_y=m_BeginPoint.y-old_begin.y;
	int end_off_x=m_EndPoint.x-old_end.x;
	int end_off_y=m_EndPoint.y-old_end.y;
	LinkItr it;
	int size=(int)m_LinkList->size();
	for (int i=0;i<size;i++)
	{
		LinkArrow* link=&(*m_LinkList)[i];
		if (begin_off_x!=0 || begin_off_y!=0 || end_off_x!=0 || end_off_y!=0)
		{
			if (link->cp.x==old_begin.x)
			{
				((CArrowUnit*)(link->unit))->LinkMove(link->cp,m_BeginPoint.x,(m_BeginPoint.y+m_EndPoint.y)/2);
				link->cp.x=m_BeginPoint.x;
				link->cp.y=(m_BeginPoint.y+m_EndPoint.y)/2;
			}
			if (link->cp.x==old_end.x)
			{
				((CArrowUnit*)(link->unit))->LinkMove(link->cp,m_EndPoint.x,(m_BeginPoint.y+m_EndPoint.y)/2);
				link->cp.x=m_EndPoint.x;
				link->cp.y=(m_BeginPoint.y+m_EndPoint.y)/2;
			}
			if (link->cp.y==old_end.y)
			{
				((CArrowUnit*)(link->unit))->LinkMove(link->cp,(m_BeginPoint.x+m_EndPoint.x)/2,m_EndPoint.y);
				link->cp.x=(m_BeginPoint.x+m_EndPoint.x)/2;
				link->cp.y=m_EndPoint.y;
			}
			if (link->cp.y==old_begin.y)
			{
				((CArrowUnit*)(link->unit))->LinkMove(link->cp,(m_BeginPoint.x+m_EndPoint.x)/2,m_BeginPoint.y);
				link->cp.x=(m_BeginPoint.x+m_EndPoint.x)/2;
				link->cp.y=m_BeginPoint.y;
			}
		}


	}
}
BOOL CTextUnit::ContainUnit(CUnit* unit)
{
	return FALSE;
}
CPoint* CTextUnit::GetVertex(int &count)
{
	CPoint* p=new CPoint[4];
	p[0]=m_BeginPoint;
	p[1].x=m_EndPoint.x;
	p[1].y=m_BeginPoint.y;
	p[2]=m_EndPoint;
	p[3].x=m_BeginPoint.x;
	p[3].y=m_EndPoint.y;
	count=4;
	return p;
}

void CTextUnit::AttachTracker()
{
	((CMyRectTracker*)m_Tracker)->m_rect.SetRect(m_BeginPoint,m_EndPoint);
}

BOOL CTextUnit::AllowText()
{
	return TRUE;
}
void CTextUnit::AddLink(LinkArrow link)
{
	m_LinkList->push_back(link);
}
void CTextUnit::RemoveLink(LinkArrow link)
{
	LinkItr it;
	for (it=m_LinkList->begin();it!=m_LinkList->end();it++)
	{
		LinkArrow la=*it;
		if (la.cp==link.cp && la.unit->Equals(link.unit))
		{
			m_LinkList->erase(it);
			break;
		}
	}
}
void CTextUnit::ShowText(CDC* pDC, bool isBkColor)
{
	int i;
	if( isBkColor )
	{		
		COLORREF clr;
		clr = pDC->SetTextColor(pDC->GetBkColor());
		for (i = 0; i < (int)m_text.size(); ++ i )
			pDC->TextOut(m_text[i].textPt.x, m_text[i].textPt.y, m_text[i].text);	
		pDC->SetTextColor(clr);
	}
	else
	{
		for (i = 0; i < (int)m_text.size(); ++ i )
			pDC->TextOut(m_text[i].textPt.x, m_text[i].textPt.y, m_text[i].text);
	}
}

void CTextUnit::CalTextPos(CDC* pDC)
{
	TEXTMETRIC tm;
	pDC->GetTextMetrics(&tm);

	CPoint centerPt;
	centerPt.y = (m_EndPoint.y - m_BeginPoint.y - (LONG)m_text.size() * tm.tmHeight)/2;
	centerPt.y += m_BeginPoint.y;
	centerPt.x = (m_BeginPoint.x + m_EndPoint.x)/2;

	CSize sz;
	for( int i = 0; i < (int)m_text.size(); ++ i )
	{
		sz = pDC->GetTextExtent(m_text[i].text);		
		m_text[i].textPt.x = centerPt.x - sz.cx/2;
		m_text[i].textPt.y = centerPt.y;
		centerPt.y += tm.tmHeight;	
	}

	ShowText(pDC, false);
	CString temp = m_text[m_caretPos.x-1].text.Left(m_caretPos.y);
	sz = pDC->GetTextExtent(temp);
	m_caretPt.x = m_text[m_caretPos.x-1].textPt.x + sz.cx;
	m_caretPt.y = m_text[m_caretPos.x-1].textPt.y;
}

void CTextUnit::TrackBroad(CPoint old_begin,CPoint old_end)
{

}
void CTextUnit::DistachTracker()
{
	((CRectTracker*)m_Tracker)->m_rect.SetRect(0,0,0,0);
}